using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Services;
using MainGame.GamePlay;

namespace MainGame.Menu
{
  public class CardRenderer
  {
    public int value;
    public int seed;
    public Rectangle position;
    public bool isSelected;
    public Color color;
  }

  public interface ITutorialPanel
  {
    event MenuEvent OnOkClicked;
  }

  public class TutorialPanel : BaseMenu, ITutorialPanel
  {

    Button TutorialBackBtn, Next, Prev, tutorialCheckBox;
    int PageNum;
    static readonly int TotalPages = 4;
    Vector2 savedPos;
    public bool Animated = false, Transition = true, tutorialChecked;
    public int Direction = 1, AnimVelocity = 60;    
    SpriteBatch spriteBatch;
    Color textColor, TransitionColor = Color.Black, colorDisplayString= Color.Yellow;
    SpriteFont smallFont;
    Texture2D check, Deck_Texture, texture_back_card, Backgnd, box, white;
    SpriteFont BaveuseFont;

    int CARD_WIDTH = 75;
    int CARD_HEIGHT = 110;
    List<CardRenderer> Cards;
    CardRenderer ExtractCard, ExtractCard2;
    bool Deck = false;


    public TutorialPanel(Game game, MenuDepths depth)
      : base(game, depth)
    {
      game.Services.AddService(typeof(ITutorialPanel), this);
    }

    protected override void Dispose(bool disposing)
    {
      Game.Services.RemoveService(typeof(ITutorialPanel));
      base.Dispose(disposing);
    }

    public override void Initialize()
    {
      var content = Game.Content;
      spriteBatch = Game.GetContext().SpriteBatch;
      //background = content.Load<Texture2D>(@"Images//Backgrounds//BG_" + Game.GetContext().currentConfig.chosenBackground);      
      white = content.Load<Texture2D>(@"white_pixel");
      box = content.Load<Texture2D>(@"Images//Menu//roundedBox");
      Backgnd = content.Load<Texture2D>(@"Images//Backgrounds//BG_ClassicRed");      
      bounds = new Rectangle(30, 20, Game.GraphicsDevice.Viewport.Width - 60, Game.GraphicsDevice.Viewport.Height - 60);

      BaveuseFont = content.Load<SpriteFont>("baveuse_small");
      smallFont = Game.Content.Load<SpriteFont>("small_font");

      Deck_Texture = Game.Content.Load<Texture2D>(@"Images//Decks//Deck_" + Game.GetContext().currentConfig.chosenDeck);
      texture_back_card = content.Load<Texture2D>(@"Images//Decks//Back_" + Game.GetContext().currentConfig.chosenDeck);
      
      Cards = new List<CardRenderer>();
      ExtractCard = new CardRenderer(){ value = 2, seed = 3, position = new Rectangle(430 + 10, bounds.Y + 135, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false};
      
      savedPos.X = bounds.X;
      PageNum = 1;
      
      // Load buttons
      TutorialBackBtn = new Button(Game, @"Images//Menu//button2", new Rectangle(330, (int)bounds.Y + 410, 120, 50), Color.Blue, "small_font", Locale.Strings.Exit, Color.White);
      AddButton(TutorialBackBtn, () =>
      {
        TutorialBackBtn.touched = true;       
        Animated = true;
        Direction = -1;
        TransitionColor = Color.Black;
      });

      Next = new Button(Game, @"Images//Menu//button2", new Rectangle(650, (int)bounds.Y + 400, 140, 55), Color.Green, "small_font", Locale.Strings.Next, Color.White);
      AddButton(Next, () =>
      {
        if (Next.color != Color.Green) return;

        PageNum++;
        if (PageNum >= TotalPages)
        {
          PageNum = TotalPages;
          
          Next.color = new Color(Next.color.R, Next.color.G, Next.color.B, 100);
        }
        else
        {
          Next.color = Color.Green;
          Prev.color = Color.Green;
        }
        TransitionColor = Color.Black;
        SetPage(PageNum);
      });

      Prev = new Button(Game, @"Images//Menu//button2", new Rectangle(10, (int)bounds.Y + 400, 140, 55), new Color(Next.color.R, Next.color.G, Next.color.B, 100), "small_font", Locale.Strings.Previous, Color.White);
      AddButton(Prev, () =>
      {
        if (Prev.color != Color.Green) return;

        PageNum--;
        if (PageNum <= 1)
        {
          PageNum = 1;          
          Prev.color = new Color(Prev.color.R, Prev.color.G, Prev.color.B, 100);
        }
        else
        {
          Prev.color = Color.Green;
          Next.color = Color.Green;
        }
        TransitionColor = Color.Black; 
        SetPage(PageNum);
      });


      check = Game.Content.Load<Texture2D>(@"Images//Menu//Check");

      //textColor = new Color(0, 0, 120);
      textColor = colorDisplayString;

      SetPage(1);

      base.Initialize();
    }

    /// <summary>
    /// Setta i parametri della pagina e dell'animazione associata
    /// </summary>
    /// <param name="pageNum"></param>
    private void SetPage(int pageNum)
    {
      Cards.Clear();
      tutorialCheckBox.bounds.X = -100;

      if (pageNum == 1) 
      {
        Cards.Add(new CardRenderer() { value = 1, seed = 0, position = new Rectangle(430 + 10, bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 3, seed = 2, position = new Rectangle(430 + 10 + (CARD_WIDTH * 1), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 5, seed = 1, position = new Rectangle(430 + 10 + (CARD_WIDTH * 2), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 8, seed = 3, position = new Rectangle(430 + 10 + (CARD_WIDTH * 3), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
    
        Cards.Add(new CardRenderer() { value = 6, seed = 3, position = new Rectangle(430 + 10, bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false});
        Cards.Add(new CardRenderer() { value = 10, seed = 1, position = new Rectangle(430 + 10 + (CARD_WIDTH * 1), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 9, seed = 0, position = new Rectangle(430 + 10 + (CARD_WIDTH * 2), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 2, seed = 2, position = new Rectangle(430 + 10 + (CARD_WIDTH * 3), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });

        Deck = false;
        // Selezioni
        Sel1 = 1; Sel2 = 3; Sel3 = 0;
      }

      if (pageNum == 2)
      {
        Cards.Add(new CardRenderer() { value = 4, seed = 1, position = new Rectangle(430 + 10, bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 6, seed = 2, position = new Rectangle(430 + 10 + (CARD_WIDTH * 1), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 11, seed = 0, position = new Rectangle(430 + 10 + (CARD_WIDTH * 2), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 4, seed = 2, position = new Rectangle(430 + 10 + (CARD_WIDTH * 3), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });

        Cards.Add(new CardRenderer() { value = 9, seed = 1, position = new Rectangle(430 + 10, bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 12, seed = 0, position = new Rectangle(430 + 10 + (CARD_WIDTH * 1), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 3, seed = 3, position = new Rectangle(430 + 10 + (CARD_WIDTH * 2), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 13, seed = 0, position = new Rectangle(430 + 10 + (CARD_WIDTH * 3), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });

        Deck = false;
        // Selezioni
        Sel1 = 2; Sel2 = 5; Sel3 = 7;
      }

      if (pageNum == 3)
      {
        Cards.Add(new CardRenderer() { value = 6, seed = 2, position = new Rectangle(450 + 10 + (CARD_WIDTH * 1), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 8, seed = 0, position = new Rectangle(450 + 10 + (CARD_WIDTH * 2), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 4, seed = 2, position = new Rectangle(450 + 10 + (CARD_WIDTH * 3), bounds.Y + 125, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });

        Cards.Add(new CardRenderer() { value = 12, seed = 3, position = new Rectangle(450 + 10 + (CARD_WIDTH * 1), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 9, seed = 3, position = new Rectangle(450 + 10 + (CARD_WIDTH * 2), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });
        Cards.Add(new CardRenderer() { value = 10, seed = 0, position = new Rectangle(450 + 10 + (CARD_WIDTH * 3), bounds.Y + 240, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false });

        Deck = true;
        ExtractCard = new CardRenderer(){ value = 2, seed = 3, position = new Rectangle(430 + 7, 135 - 7, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false};
        ExtractCard2 = new CardRenderer() { value = 7, seed = 2, position = new Rectangle(430 + 7, 135 - 7, CARD_WIDTH, CARD_HEIGHT), color = Color.White, isSelected = false };
        
        Sel1 = 4; Sel2 = 2;
      }

      if (pageNum == 4)
      {
        Deck = false;
        tutorialCheckBox.bounds.X = bounds.X + 170;
      }

      AnimationTime = 0;
    }

    /// <summary>
    /// Update
    /// </summary>
    /// <param name="gameTime"></param>
    public override void Update(GameTime gameTime)
    {
      // Input: back button pressed
      if (((Game1)Game).IsBackButtonPressed())
      {
        TutorialBackBtn.touched = true;
        Animated = true;
        Direction = -1;
        TransitionColor = Color.Black;
      }

      if (Animated)
      {
        // Animate the menu items to follow the menu sliding animation

        bounds.Y += Direction * AnimVelocity;

        foreach (Button b in (from cb in buttons select cb.b))
          b.bounds.Y += Direction * AnimVelocity;

        if (bounds.Y < -Game.GraphicsDevice.Viewport.Height)        
          if (OnOkClicked != null)
            OnOkClicked();
      }

      if (TransitionColor.A > 10) TransitionColor.A -= 10;
       else TransitionColor.A = 0;

      if( PageNum == 1) Animation1();
      if (PageNum == 2) Animation2();
      if (PageNum == 3) Animation3();

      base.Update(gameTime);
    }

    int AnimationTime = 0;
    int SelectionCounter = 0, Sel1 = 1, Sel2 = 3, Sel3 = 0;
    /// <summary>
    /// Gestisce l'animazione della prima Pagina
    /// </summary>
    private void Animation1()
    {
      AnimationTime++;
      Message = Locale.Strings.Tutorial;

      if (Cards.Count == 0) return;

      if (AnimationTime == 10)
      {
        Cards[Sel1].isSelected = true;
        Cards[Sel1].position.Y -= 5;
      }

      if (AnimationTime == 40)
      {
        Cards[Sel2].isSelected = true;
        Cards[Sel2].position.Y -= 5;
      }

      if (AnimationTime > 50)
      {
        Cards[Sel1].position.Y -= 10;
        Cards[Sel2].position.Y -= 10;
      }

      if (AnimationTime > 100) 
      { 
        SetPage(1); 
        AnimationTime = 0;

        SelectionCounter++; SelectionCounter %= 4;
        if (SelectionCounter == 0) { Sel1 = 1; Sel2 = 3; }
        if (SelectionCounter == 1) { Sel1 = 0; Sel2 = 5; }
        if (SelectionCounter == 2) { Sel1 = 6; Sel2 = 7; }
        if (SelectionCounter == 3) { Sel1 = 2; Sel2 = 4; }
      }
    }

    /// <summary>
    /// Gestisce l'animazione della seconda Pagina
    /// </summary>
    private void Animation2()
    {
      AnimationTime++;
      Message = Locale.Strings.Tutorial;

      if (Cards.Count == 0) return;

      if (AnimationTime == 10)
      {
        Cards[Sel1].isSelected = true;
        Cards[Sel1].position.Y -= 5;
      }

      if (AnimationTime == 40)
      {
        Cards[Sel2].isSelected = true;
        Cards[Sel2].position.Y -= 5;
      }

      if (AnimationTime == 70)
      {
        Cards[Sel3].isSelected = true;
        Cards[Sel3].position.Y -= 5;
      }

      if (AnimationTime > 90)
      {
        Cards[Sel1].position.Y -= 10;
        Cards[Sel2].position.Y -= 10;
        Cards[Sel3].position.Y -= 10;
      }

      if (AnimationTime > 150)
      {
        SetPage(2);
        AnimationTime = 0;
      }
    }

    /// <summary>
    /// Gestisce l'animazione della seconda Pagina
    /// </summary>
    private void Animation3()
    {
      AnimationTime++;
      Message = Locale.Strings.Tutorial;

      if (Cards.Count == 0) return;

      if (AnimationTime == 10)
      {
        Cards[Sel1].isSelected = true;
        Cards[Sel1].position.Y -= 5;
      }

      if (AnimationTime == 40)
      {
        ExtractCard.isSelected = true;
        ExtractCard.position.Y -= 5;
      }

      if (AnimationTime > 70)
      {
        Cards[Sel1].position.Y -= 10;
        ExtractCard.position.Y -= 10;
      }

      if (AnimationTime > 120)
      {
        SetPage(3);

        SelectionCounter++; 
        SelectionCounter %= 3;

        if (SelectionCounter == 0) { Sel1 = 4; ExtractCard.value = 2; ExtractCard.seed = 3; ExtractCard2.value = 7; ExtractCard2.seed = 2; }
        if (SelectionCounter == 1) { Sel1 = 2; ExtractCard.value = 7; ExtractCard.seed = 2; ExtractCard2.value = 5; ExtractCard2.seed = 3; }
        if (SelectionCounter == 2) { Sel1 = 0; ExtractCard.value = 5; ExtractCard.seed = 3; ExtractCard2.value = 2; ExtractCard2.seed = 3; }
        
        AnimationTime = 0;
      }
    }

    /// <summary>
    /// Draw
    /// </summary>
    /// <param name="gameTime"></param>
    public override void Draw(GameTime gameTime)
    {

      //if (Animated) return;
      spriteBatch.Begin();

      // BackGround
      spriteBatch.Draw(Backgnd, bounds, Color.White);
      // Cornice
      spriteBatch.Draw(white, new Rectangle(bounds.X, bounds.Y, 5, bounds.Height), Color.Black);
      spriteBatch.Draw(white, new Rectangle(bounds.X, bounds.Y, bounds.Width, 5), Color.Black);
      spriteBatch.Draw(white, new Rectangle(bounds.X + bounds.Width - 5, bounds.Y, 5, bounds.Height), Color.Black);
      spriteBatch.Draw(white, new Rectangle(bounds.X, bounds.Y + bounds.Height, bounds.Width, 5), Color.Black);

      if (!Animated)
      {

        // Carte
        for (int i = 0; i < Cards.Count; i++)
          DrawCard(Cards[i]);
        //spriteBatch.Draw(Deck_Texture, new Rectangle(300 , 100 , CARD_WIDTH, CARD_HEIGHT), Color.White);


        if (Deck)
        {
          // Carte Estratte
          for (int i = 0; i < 7; i++)
            spriteBatch.Draw(Deck_Texture, new Rectangle(430 + i, 135 - i, CARD_WIDTH, CARD_HEIGHT), new Rectangle((Deck_Texture.Width / 13) * (1), (Deck_Texture.Height / 4) * (1), Deck_Texture.Width / 13, Deck_Texture.Height / 4), Color.White, 0.0f, Vector2.Zero, SpriteEffects.None, 1.0f);

          DrawCard(ExtractCard2);
          DrawCard(ExtractCard);

          // Mazzo
          for (int i = 0; i < 10; i++)
            spriteBatch.Draw(texture_back_card, new Rectangle(430 + i, 270 - i, CARD_WIDTH, CARD_HEIGHT), Color.White);
        }

        // Pagina
        spriteBatch.DrawString(BaveuseFont, PageNum + "/" + TotalPages, new Vector2((int)bounds.X + 695, (int)bounds.Y), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 1.00f);
        spriteBatch.DrawString(BaveuseFont, PageNum + "/" + TotalPages, new Vector2((int)bounds.X + 696, (int)bounds.Y + 1), Color.Yellow, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.99f);

        DrawMessage(new Vector2(bounds.X + 10, 100));
      }
      // Transition
      spriteBatch.Draw(Backgnd, bounds, TransitionColor);

      spriteBatch.End();

      base.Draw(gameTime);
    }

    /// <summary>
    /// Disegna la carta
    /// </summary>
    /// <param name="card"></param>
    private void DrawCard(CardRenderer card)
    {
      Color ColorCard = card.color;

      if(card.isSelected)
      {
        ColorCard = Color.Yellow;
      }
      
      // Carta
      spriteBatch.Draw(Deck_Texture, card.position, new Rectangle((Deck_Texture.Width / 13) * (card.value - 1), (Deck_Texture.Height / 4) * (card.seed), Deck_Texture.Width / 13, Deck_Texture.Height / 4), ColorCard, 0.0f, Vector2.Zero, SpriteEffects.None, 0.1f);

    } // Fine DrawCard

    string Message = "Ciao";
    /// <summary>
    /// 
    /// </summary>
    /// <param name="position"></param>
    private void DrawMessage(Vector2 position)
    {
      if (PageNum == 1)
      {
        // Box
        spriteBatch.Draw(box, new Rectangle(bounds.X + 5, bounds.Y + 70, bounds.Width / 2, bounds.Height - 70), new Color(120, 120, 120, 120));

        spriteBatch.DrawString(smallFont, Locale.Strings.TutorialPage1.Replace("\\n", "\n"), position, Color.Black);
      }
      if (PageNum == 2)
      {
        // Box
        spriteBatch.Draw(box, new Rectangle(bounds.X + 5, bounds.Y + 70, bounds.Width / 2, bounds.Height - 70), new Color(120, 120, 120, 120));

        spriteBatch.DrawString(smallFont, Locale.Strings.TutorialPage2.Replace("\\n", "\n"), position, Color.Black);
      }
      if (PageNum == 3)
      {
        // Box
        spriteBatch.Draw(box, new Rectangle(bounds.X + 5, bounds.Y + 70, bounds.Width / 2, bounds.Height - 70), new Color(120, 120, 120, 120));

        spriteBatch.DrawString(smallFont, Locale.Strings.TutorialPage3.Replace("\\n", "\n"), position, Color.Black);
      }
      if (PageNum == 4)
      {
        // Box
        spriteBatch.Draw(white, new Rectangle(bounds.X + 5, bounds.Y + 70, bounds.Width - 10, bounds.Height - 70), new Color(120, 120, 120, 120));

        spriteBatch.DrawString(smallFont, Locale.Strings.DifficultyEasy, position + new Vector2(40, 51), Color.Green, 0.0f, Vector2.Zero, 0.9f, SpriteEffects.None, 1.0f);
        spriteBatch.DrawString(smallFont, Locale.Strings.DifficultyMedium, position + new Vector2(40, 103), Color.Yellow, 0.0f, Vector2.Zero, 0.9f, SpriteEffects.None, 1.0f);
        spriteBatch.DrawString(smallFont, Locale.Strings.DifficultyHard, position + new Vector2(40, 130), Color.Red, 0.0f, Vector2.Zero, 0.9f, SpriteEffects.None, 1.0f);

        spriteBatch.DrawString(smallFont, Locale.Strings.TutorialPage4.Replace("\\n", "\n"), position + new Vector2(30, 0), Color.Black, 0.0f, Vector2.Zero, 0.8f, SpriteEffects.None, 1.0f);

        if (tutorialChecked)
          spriteBatch.Draw(check, new Rectangle(tutorialCheckBox.bounds.Center.X - 16, tutorialCheckBox.bounds.Top - 10, 40, 40), colorDisplayString);

        spriteBatch.DrawString(smallFont, Locale.Strings.ShowTutorialNextTime, new Vector2((int)tutorialCheckBox.bounds.Left + tutorialCheckBox.bounds.Width + 10, tutorialCheckBox.bounds.Top), Color.Yellow);
      }

      // Titolo
      spriteBatch.DrawString(BaveuseFont, Locale.Strings.Tutorial, new Vector2((int)bounds.X + 10, (int)bounds.Y), Color.Black, 0.0f, Vector2.Zero, 2.5f, SpriteEffects.None, 1.0f);
      spriteBatch.DrawString(BaveuseFont, Locale.Strings.Tutorial, new Vector2((int)bounds.X + 11, (int)bounds.Y + 1), Color.Yellow, 0.0f, Vector2.Zero, 2.5f, SpriteEffects.None, 0.99f);
    }

    public event MenuEvent OnOkClicked;
  }
}
